package top.ashman.demo.springcloud.hystrix;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

/**
 * @see com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect
 *
 * @author sunzhaojie
 * @date 2018-12-10
 */
@RestController
@RequestMapping("/my")
public class MyController {
    private final MyService myService;

    public MyController(MyService myService) {
        this.myService = myService;
    }

    @GetMapping("/hello")
    public Mono<String> hello() {
        System.out.println("Hello World");
        return Mono.just("Hello World");
    }

    @GetMapping("/hello/{name}")
    public Mono<String> hello(@PathVariable String name) {
        var helloMore = new ArrayList<String>();
        helloMore.add(myService.hello(name));
        helloMore.add(myService.hello(name));
        helloMore.add(myService.hello(name + "XXX"));
        helloMore.add(myService.hello(name + "XXX"));
        helloMore.add(myService.hello());
        helloMore.add(myService.hello());
        helloMore.add(myService.hello(name, name + "XXX"));
        helloMore.add(myService.hello(name, name + "XXX"));
        return Mono.just(helloMore.toString());
    }

    @HystrixCommand(
            groupKey = "myGroupKey",
            commandKey = "myCommandKey",
            fallbackMethod = "sleepAndHelloFallback",
            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
            }, threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "3")
            })
    @GetMapping("/sleep/{milliseconds}")
    public Mono<String> sleepAndHello(@PathVariable Long milliseconds) throws InterruptedException {
        // noinspection BlockingMethodInNonBlockingContext
        TimeUnit.MILLISECONDS.sleep(milliseconds);
        return Mono.just("Sleep " + milliseconds + " milliseconds and Hello World");
    }

    @HystrixCommand(
            groupKey = "myGroupKey",
            commandKey = "myCommandKey2",
            fallbackMethod = "sleepAndHelloFallback")
    @GetMapping("/sleep/2/{milliseconds}")
    public Mono<String> sleepAndHello2(@PathVariable Long milliseconds) throws InterruptedException {
        // noinspection BlockingMethodInNonBlockingContext
        TimeUnit.MILLISECONDS.sleep(milliseconds);
        return Mono.just("Sleep (2) " + milliseconds + " milliseconds and Hello World");
    }

    public Mono<String> sleepAndHelloFallback(Long milliseconds) {
        System.out.println("Sleep " + milliseconds + " ms cause timeout");
        return Mono.just("Hello World (From Fallback)");
    }
}
